﻿using CTM.Web.Filters;
using CTM.Web.Models.View.Report;
using CTM.Web.Services;
using CTM.Web.Utils;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CTM.Web.Controllers
{
    public class ReportController : Controller
    {
        // initialize service objects
        private IPostService postService;
        private IAccountService accountService; // employee or user service
        private IOrgService orgService;
        private ApplicationUserManager userManager;

        public ApplicationUserManager UserManager
        {
            get
            {
                return userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                userManager = value;
            }
        }

        public ReportController(IPostService postService, IAccountService accountService, IOrgService orgService)
        {
            this.postService = postService;
            this.accountService = accountService;
            this.orgService = orgService;
        }

        // GET: Report
        [ApplicationAuthorize(Permissions = Rights.View + Modules.Conversation)]
        public ActionResult Index(string id)
        {
            id = string.IsNullOrEmpty(id) ? GlobalVariables.CurrentUser.Id : id;
            GlobalVariables.SelectedUser = accountService.GetById(id);

            if (!ApplicationHelpers.IsManager(accountService, UserManager, GlobalVariables.CurrentUser.Id, GlobalVariables.SelectedUser.Id)
                && GlobalVariables.CurrentUser.Id != GlobalVariables.SelectedUser.Id)
            {
                return RedirectToAction("Index", "Feedback", new { id = id });
            }

            List<Guid> lowerOrgs = null;
            ViewBag.Tree = ApplicationHelpers.BuildTree(accountService, UserManager, orgService, GlobalVariables.CurrentUser.Id, out lowerOrgs);

            var searchModel = new ReportSearchModel
            {
                Year = DateTime.UtcNow.Year,
                Orgs = lowerOrgs,
                Statuses = Enum.GetValues(typeof(Emoticon)).Cast<Emoticon>().ToList(),
                Types = Enum.GetValues(typeof(PostType)).Cast<PostType>().ToList(),
                IncludeIndirectEmployees = false
            };

            var viewModel = GetData(id, searchModel);
            ViewBag.PageSize = searchModel.PageSize ?? 10;
            return View(viewModel);
        }

        public ActionResult SummaryPartial(string id, ReportSearchModel searchModel)
        {
            searchModel.Statuses = Enum.GetValues(typeof(Emoticon)).Cast<Emoticon>().ToList();
            searchModel.Types = Enum.GetValues(typeof(PostType)).Cast<PostType>().ToList();
            
            var viewModel = GetData(id, searchModel);
            viewModel.IncludeIndirectEmployees = searchModel.IncludeIndirectEmployees;
            ViewBag.PageSize = searchModel.PageSize ?? 10;      
            var htmlSummary = this.RenderRazorViewToString("_Summary", viewModel);
            return Json(new
            {
                totalConversation = viewModel.ConversationDetails.Count(),
                totalFeedback = viewModel.FeedbackDetails.Count(),
                chartConversationStatusData = viewModel.ChartConversationStatusData,
                chartConversationClassificationData = viewModel.ChartConversationClassificationData,
                chartFeedbackData = viewModel.ChartFeedbackData,
                html = htmlSummary
            });
        }

        public ActionResult ConversationPartial(string id, ReportSearchModel searchModel)
        {
            bool isHR = ApplicationHelpers.IsHR(UserManager, GlobalVariables.CurrentUser.Id);

            var details = postService.GetConversations(GlobalVariables.CurrentUser, searchModel, isHR);
            ViewBag.PageSize = searchModel.PageSize ?? 10;
            return PartialView("_Conversation", details);
        }

        public ActionResult FeedbackPartial(string id, ReportSearchModel searchModel)
        {
            bool isHR = ApplicationHelpers.IsHR(UserManager, GlobalVariables.CurrentUser.Id);
            var details = postService.GetFeedbacks(GlobalVariables.CurrentUser, searchModel, isHR);
            ViewBag.PageSize = searchModel.PageSize ?? 10;
            return PartialView("_Feedback", details);
        }

        #region Method

        private ReportViewModel GetData(string id, ReportSearchModel searchModel)
        {
            var viewModel = new ReportViewModel();
            viewModel.Id = id;
            if(searchModel.Year.HasValue)
                viewModel.Year = searchModel.Year.Value;
            viewModel.IncludeIndirectEmployees = searchModel.IncludeIndirectEmployees;

            bool isHR = ApplicationHelpers.IsHR(UserManager, GlobalVariables.CurrentUser.Id);
            var conversations = postService.GetConversations(GlobalVariables.CurrentUser, searchModel, isHR).ToList();
            viewModel.ConversationDetails = conversations;
            
            var frown = conversations.Sum(c => c.NoFrownPost);
            var neutral = conversations.Sum(c => c.NoNeutralPost);
            var smile = conversations.Sum(c => c.NoSmilePost);
            viewModel.TotalConversations = frown + neutral + smile;

            viewModel.StatusSummaries[Emoticon.Frown] = frown;
            viewModel.StatusSummaries[Emoticon.Neutral] = neutral;
            viewModel.StatusSummaries[Emoticon.Smile] = smile;
            
            viewModel.ChartConversationStatusData.Add(new ChartItem { label = Emoticon.Smile.GetDescription(), value = smile });
            viewModel.ChartConversationStatusData.Add(new ChartItem { label = Emoticon.Neutral.GetDescription(), value = neutral });
            viewModel.ChartConversationStatusData.Add(new ChartItem { label = Emoticon.Frown.GetDescription(), value = frown });

            var career = conversations.Sum(c => c.NoCareerPost);
            var goal = conversations.Sum(c => c.NoGoalsPost);
            var individual = conversations.Sum(c => c.NoIndividualPost);

            viewModel.ClassificationSummaries[PostType.Career] = career;
            viewModel.ClassificationSummaries[PostType.Goals] = goal;
            viewModel.ClassificationSummaries[PostType.Individual] = individual;
            viewModel.ChartConversationClassificationData.Add(new ChartItem { label = PostType.Goals.GetDescription(), value = goal });
            viewModel.ChartConversationClassificationData.Add(new ChartItem { label = PostType.Career.GetDescription(), value = career });
            viewModel.ChartConversationClassificationData.Add(new ChartItem { label = PostType.Individual.GetDescription(), value = individual });

            // Get feedbacks from DB            
            var feedbacks = postService.GetFeedbacks(GlobalVariables.CurrentUser, searchModel, isHR).ToList();
            viewModel.FeedbackDetails = feedbacks;

            frown = feedbacks.Sum(c => c.NoFrownPost);
            neutral = feedbacks.Sum(c => c.NoNeutralPost);
            smile = feedbacks.Sum(c => c.NoSmilePost);
            viewModel.TotalFeedbacks = frown + neutral + smile;

            viewModel.FeedbackSummaries[Emoticon.Frown] = frown;
            viewModel.FeedbackSummaries[Emoticon.Neutral] = neutral;
            viewModel.FeedbackSummaries[Emoticon.Smile] = smile;

            viewModel.ChartFeedbackData.Add(new ChartItem { label = Emoticon.Smile.GetDescription(), value = smile });
            viewModel.ChartFeedbackData.Add(new ChartItem { label = Emoticon.Neutral.GetDescription(), value = neutral });
            viewModel.ChartFeedbackData.Add(new ChartItem { label = Emoticon.Frown.GetDescription(), value = frown });

            return viewModel;
        }

        #endregion
    }
}